package com.ccp.dev.workflow.service;
import com.ccp.dev.core.basic.engine.GroovyScriptEngine;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.workflow.dao.BpmNodeRuleDao;
import com.ccp.dev.workflow.model.BpmNodeRule;
import com.ccp.dev.workflow.model.BpmNodeSet;
import org.flowable.engine.RuntimeService;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 流程跳转规则类。<br>
 * 返回流程跳转节点id，如果返回为空则忽略跳转，按照默认的规则执行。<br>
 * <pre>
 * 实现原理：
 * 1.在流程节点规则数据库中根据节点deployId和节点名称获取跳转规则列表。
 * 2.在流程规则中传入流程变量。
 * 3.根据流程变量循环计算流程条件，如果流程条件返回true，则返回跳转节点。
 * 4.如果循环完毕，没有找到跳转节点，则忽略流程跳转规则，使用流程默认跳转进行跳转。 
 * </pre>
 * @author jiayueqiao
 *
 */
@Service
public class JumpRule {
	/**
	 * 当所有的规则都不发生作用时，返回该值。
	 */
	public static final String RULE_INVALID="_RULE_INVALID";
	
	private Logger logger=LoggerFactory.getLogger(JumpRule.class);
	
	@Resource
	private BpmNodeRuleDao bpmNodeRuleDao;
	@Resource
	private GroovyScriptEngine scriptEngine;
	@Resource
	private RuntimeService runtimeService;
	
	public String evaluate(TaskEntity taskEntity, Short isJumpForDef){
		logger.debug("enter the rule decision");
		String activityId=taskEntity.getTaskDefinitionKey();
		String procDefId=taskEntity.getProcessDefinitionId();
		String instanceId = taskEntity.getProcessInstanceId();
		//获取规则列表
		List<BpmNodeRule> ruleList=bpmNodeRuleDao.getByProcDefIdNodeId(procDefId, activityId);
		//获取流程变量，参与规则的计算。
		Map<String, Object> vars=new HashMap<>(15);
		vars.putAll(runtimeService.getVariables(instanceId));
		if(BeanUtils.isEmpty(ruleList)){
			return "";
		}
		for(BpmNodeRule nodeRule:ruleList){
			try{
				Boolean rtn=scriptEngine.executeBoolean(nodeRule.getConditionCode(), vars);
				//返回不为空
				if(rtn!=null){
					//条件返回true，取得对应的节点，进行跳转。
					if(rtn){
						logger.debug("the last rule decision is " + nodeRule.getTargetNode() );
						return nodeRule.getTargetNode();
					}
				}
				//返回为空，说明条件表达式为空。
				else{
					logger.debug("条件表达式返回为空，请使用return语句返回!" );
				}
			} catch(Exception ex){
				logger.debug("error message: " + ex.getMessage() );
			}
		}
		if(!ruleList.isEmpty() && BpmNodeSet.RULE_INVALID_NO_NORMAL.equals(isJumpForDef)){
			return RULE_INVALID;
		}
		return "";
	}

}
